package com.example.data.factory.service.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.data.factory.common.Dto.*;
import com.example.data.factory.common.Exception.DuplicateDataException;
import com.example.data.factory.common.VO.SearchDataAssetDetailVo;
import com.example.data.factory.common.common.StringConstant;
import com.example.data.factory.common.result.PageVO;
import com.example.data.factory.common.result.R;
import com.example.data.factory.common.util.CommonUtil;
import com.example.data.factory.entity.entity.DataAssetCatalog;
import com.example.data.factory.entity.entity.DataAssetField;
import com.example.data.factory.entity.entity.DataAssetInfo;
import com.example.data.factory.mapper.mapper.DataAssetCatalogMapper;
import com.example.data.factory.mapper.mapper.DataAssetInfoMapper;
import com.example.data.factory.service.service.DataAssetCatalogService;
import com.example.data.factory.service.service.DataAssetFieldService;
import com.example.data.factory.service.service.DataAssetInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据资产表信息 服务实现类
 * </p>
 *
 * @author lhy
 * @since 2025-03-03
 */
@Service
public class DataAssetInfoServiceImpl extends ServiceImpl<DataAssetInfoMapper, DataAssetInfo> implements DataAssetInfoService {

    @Resource
    private DataAssetFieldService dataAssetFieldService;
    @Resource
    private DataAssetCatalogService dataAssetCatalogService;
    @Resource
    private CommonUtil commonUtil;
    @Resource
    private DataAssetCatalogMapper dataAssetCatalogMapper;

    @Override
    public R<DataAssetInfo> search(SearchDataAssetInfoDto searchDataAssetInfoDto) {
        Page<DataAssetInfo> page = new Page<> ( searchDataAssetInfoDto.getPageNumber (), searchDataAssetInfoDto.getPageSize () );
        LambdaQueryWrapper<DataAssetInfo> wrapper = new LambdaQueryWrapper<> ();
        if (Objects.nonNull ( searchDataAssetInfoDto.getStatus () )) {
            wrapper.eq ( DataAssetInfo::getStatus, searchDataAssetInfoDto.getStatus () );
        }
        if (StringUtils.isNotBlank ( searchDataAssetInfoDto.getChineseName () )) {
            wrapper.like ( DataAssetInfo::getChineseName, searchDataAssetInfoDto.getChineseName () );
        }
        if (StringUtils.isNotBlank ( searchDataAssetInfoDto.getEnglishName () )) {
            wrapper.like ( DataAssetInfo::getEnglishName, searchDataAssetInfoDto.getEnglishName () );
        }
        wrapper.eq ( DataAssetInfo::getDeleted, 0 );
        Page<DataAssetInfo> page1 = this.page ( page, wrapper );
        PageVO<DataAssetInfo> pageVO = new PageVO<> ();
        BeanUtil.copyProperties ( page1, pageVO );
        return R.Success ( pageVO );

    }

    @Override
    public R<DataAssetInfo> inserts(InsertDataAssetInfoDro insertDataAssetInfoDro, HttpServletRequest request) {
        // 首先获取所有数据资产表的信息，进行查重处理
        DataAssetInfo dataAssetInfo = new DataAssetInfo ();
        BeanUtil.copyProperties ( insertDataAssetInfoDro, dataAssetInfo );
        List<DataAssetInfo> list = this.list ();

        boolean exists = list.stream ().anyMatch ( data -> data.getChineseName ().equals ( insertDataAssetInfoDro.getChineseName () ) )
                || list.stream ().anyMatch ( data -> data.getEnglishName ().equals ( insertDataAssetInfoDro.getEnglishName () ) );
        if (exists) {
            return R.Failed ( StringConstant.ERRO );
        }
        String username = commonUtil.extractUsernameFromRequest ( request );
        dataAssetInfo.setCreateBy ( username );
        dataAssetInfo.setCreateTime ( LocalDateTime.now () );
        dataAssetInfo.setUpdateTime ( LocalDateTime.now () );

        boolean save = this.save ( dataAssetInfo );
        if (save) {
            DataAssetCatalog dataAssetCatalog = new DataAssetCatalog ();
            dataAssetCatalog.setClassifyId ( insertDataAssetInfoDro.getClassifyId () );
            dataAssetCatalog.setDataAssetId ( dataAssetInfo.getId () );
            dataAssetCatalog.setUpdateTime ( LocalDateTime.now () );
            dataAssetCatalog.setCreateTime ( LocalDateTime.now () );
            // 添加保存逻辑
            dataAssetCatalogService.save ( dataAssetCatalog );
        }

        List<InsertDataAssetFieldDto> dataAssetFieldDtos = insertDataAssetInfoDro.getDataAssetFieldDtos ();
        if (dataAssetFieldDtos == null || dataAssetFieldDtos.isEmpty ()) {
            return R.Failed ( "未传入任何数字资产表字段信息" );
        }

        for (InsertDataAssetFieldDto dataAssetFieldDto : dataAssetFieldDtos) {
            DataAssetField dataAssetField = new DataAssetField ();
            dataAssetField.setCreateTime ( LocalDateTime.now () );
            dataAssetField.setUpdateTime ( LocalDateTime.now () );
            BeanUtil.copyProperties ( dataAssetFieldDto, dataAssetField );
            // 获取数据资产表中已存在的所有数据, 进行查重处理
            List<DataAssetField> list1 = dataAssetFieldService.list ( new LambdaQueryWrapper<DataAssetField> ().eq ( DataAssetField::getDataAssetId, dataAssetInfo.getId () ) );
            boolean isDuplicate = list1.stream ().anyMatch ( data -> data.getChineseName ().equals ( dataAssetFieldDto.getChineseName () )
                    || data.getEnglishName ().equals ( dataAssetFieldDto.getEnglishName () ) );
            if (isDuplicate) {
                throw new DuplicateDataException ( "Dict_data中存在重复的标签或值" );
            }
            dataAssetField.setDataAssetId ( dataAssetInfo.getId () );
            dataAssetFieldService.save ( dataAssetField );
        }
        return R.Success ( StringConstant.INSERTSUCCESS );
    }

    @Override
    public R<DataAssetInfo> updates(UpdateDataAssetInfoDto updateDataAssetInfoDto) {
        // 根据id获得需要更新的原始数据的信息
        DataAssetInfo one = this.getOne ( new LambdaQueryWrapper<DataAssetInfo> ()
                .eq ( DataAssetInfo::getId, updateDataAssetInfoDto.getId () ) );

        if (one == null || !(one.getStatus () == 0 || one.getStatus () == 2)) {
            return R.Failed ( StringConstant.UPDATEERRO );
        }

        List<DataAssetInfo> dataList = this.list (); // 假设list()返回所有记录的列表
        boolean existsDuplicate = dataList.stream ().anyMatch ( data ->
                (data.getChineseName ().equals ( updateDataAssetInfoDto.getChineseName () ) ||
                        data.getEnglishName ().equals ( updateDataAssetInfoDto.getEnglishName () )) &&
                        !data.getId ().equals ( one.getId () )
        );
        if (existsDuplicate) {
            return R.Failed ( StringConstant.ERRO );
        }

        // 更新主表信息
        DataAssetInfo dataAssetInfo = new DataAssetInfo ();
        BeanUtil.copyProperties ( updateDataAssetInfoDto, dataAssetInfo );
        dataAssetInfo.setUpdateTime ( LocalDateTime.now () );
        boolean updateMain = this.update ( dataAssetInfo, new LambdaUpdateWrapper<DataAssetInfo> ()
                .eq ( DataAssetInfo::getId, updateDataAssetInfoDto.getId () ) );

        if (!updateMain) {
            return R.Failed ( StringConstant.UPDATEFAILED );
        }

        // 获取并更新DataAssetCatalog信息
        if (updateDataAssetInfoDto.getClassifyId () != null) {
            // 查询与当前数据资产关联的DataAssetCatalog记录
            DataAssetCatalog existingCatalog = dataAssetCatalogService.getOne ( new LambdaQueryWrapper<DataAssetCatalog> ()
                    .eq ( DataAssetCatalog::getDataAssetId, updateDataAssetInfoDto.getId () ) );

            if (existingCatalog != null) {
                existingCatalog.setClassifyId ( updateDataAssetInfoDto.getClassifyId () );
                existingCatalog.setUpdateTime ( LocalDateTime.now () );
                boolean updateCatalog = dataAssetCatalogService.saveOrUpdate ( existingCatalog );
                if (!updateCatalog) {
                    return R.Failed ( "更新DataAssetCatalog失败" );
                }
            } else {
                // 如果不存在对应的记录，则创建新记录
                DataAssetCatalog newCatalog = new DataAssetCatalog ();
                newCatalog.setClassifyId ( updateDataAssetInfoDto.getClassifyId () );
                newCatalog.setDataAssetId ( updateDataAssetInfoDto.getId () );
                newCatalog.setCreateTime ( LocalDateTime.now () );
                newCatalog.setUpdateTime ( LocalDateTime.now () );
                boolean insertCatalog = dataAssetCatalogService.save ( newCatalog );
                if (!insertCatalog) {
                    return R.Failed ( "插入DataAssetCatalog失败" );
                }
            }
        }

        // 处理 DataAssetField 的同步更新
        List<UpdateDataAssetFieldDto> updateDataAssetFieldDtos = updateDataAssetInfoDto.getUpdateDataAssetFieldDtos ();
        Set<Integer> frontendIds = new HashSet<> (); // 前端传递的 id 集合

        // 收集前端传递的 id
        for (UpdateDataAssetFieldDto dto : updateDataAssetFieldDtos) {
            if (dto.getId () != null) {
                frontendIds.add ( dto.getId () );
            }
        }
        // 查询数据库中现有的 DataAssetField 数据
        List<DataAssetField> existingFields = dataAssetFieldService.list (
                new LambdaQueryWrapper<DataAssetField> ()
                        .eq ( DataAssetField::getDataAssetId, updateDataAssetInfoDto.getId () )
        );

        // 找出需要删除的 id
        Set<Integer> existingIds = existingFields.stream ()
                .map ( DataAssetField::getId )
                .collect ( Collectors.toSet () );

        Set<Integer> idsToDelete = new HashSet<> ( existingIds ); // 数据库中存在的 id
        idsToDelete.removeAll ( frontendIds ); // 差集：数据库中有但前端没有的 id

        // 删除多余的记录
        if (!idsToDelete.isEmpty ()) {
            boolean deleteSuccess = dataAssetFieldService.removeByIds ( idsToDelete );
            if (!deleteSuccess) {
                return R.Failed ( "删除多余 DataAssetField 失败" );
            }
        }
        // 更新或新增前端传递的数据
        for (UpdateDataAssetFieldDto dto : updateDataAssetFieldDtos) {
            if (dto.getId () == null) {
                // 新增操作
                DataAssetField newDataAssetField = new DataAssetField ();
                BeanUtil.copyProperties ( dto, newDataAssetField );
                newDataAssetField.setDataAssetId ( updateDataAssetInfoDto.getId () ); // 关联 DataAssetInfo
                newDataAssetField.setCreateTime ( LocalDateTime.now () );
                newDataAssetField.setUpdateTime ( LocalDateTime.now () );
                boolean insertSuccess = dataAssetFieldService.save ( newDataAssetField );
                if (!insertSuccess) {
                    return R.Failed ( "新增 DataAssetField 失败" );
                }
            } else {
                // 更新操作
                Optional<DataAssetField> optionalField = existingFields.stream ()
                        .filter ( field -> field.getId ().equals ( dto.getId () ) )
                        .findFirst ();

                if (optionalField.isPresent ()) {
                    DataAssetField dataAssetField = optionalField.get ();
                    BeanUtil.copyProperties ( dto, dataAssetField );
                    dataAssetField.setUpdateTime ( LocalDateTime.now () );
                    boolean updateSuccess = dataAssetFieldService.updateById ( dataAssetField );
                    if (!updateSuccess) {
                        return R.Failed ( "更新 DataAssetField 失败" );
                    }
                } else {
                    return R.Failed ( "编号错误: 无法找到编号为 " + dto.getId () + " 的记录" );
                }
            }
        }
        return R.Success ( StringConstant.UPDATESUCCESS );
    }

    @Override
    public R<DataAssetInfo> updatestatus(UpdateDataAssetInfoStatusDto updateDataAssetInfoStatusDto) {
        DataAssetInfo one = this.getOne ( new LambdaQueryWrapper<DataAssetInfo> ().eq ( DataAssetInfo::getId, updateDataAssetInfoStatusDto.getId () ) );
        if (one == null || Objects.isNull ( one )) {
            return R.Failed ( "找不到该数据" );
        }
        if (one.getDeleted () == 1) {
            return R.Failed ( "该数据已删除,无法进行修改" );
        }
        DataAssetInfo dataAssetInfo = new DataAssetInfo ();
        dataAssetInfo.setUpdateTime ( LocalDateTime.now () );
        boolean update = this.update ( new LambdaUpdateWrapper<DataAssetInfo> ().set ( DataAssetInfo::getStatus, updateDataAssetInfoStatusDto.getStatus () )
                .eq ( DataAssetInfo::getId, updateDataAssetInfoStatusDto.getId () ) );
        if (update) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        }
        return R.Failed ( StringConstant.UPDATEFAILED );
    }

    @Override
    public R<DataAssetInfo> delete(DeleteDataAssetInfoDto deleteDataAssetInfoDto) {
        DataAssetInfo one = this.getOne ( new LambdaQueryWrapper<DataAssetInfo> ().eq ( DataAssetInfo::getId, deleteDataAssetInfoDto.getId () ) );
        if (one == null || Objects.isNull ( one )) {
            return R.Failed ( "找不到该数据" );
        }
        if (!(one.getStatus () == 0)) {
            return R.Failed ( "只能删除未发布的数据" );
        }
        boolean update = this.update ( new LambdaUpdateWrapper<DataAssetInfo> ().set ( DataAssetInfo::getDeleted, 1 )
                .eq ( DataAssetInfo::getId, deleteDataAssetInfoDto.getId () ) );
        if (update) {
            return R.Success ( "删除成功" );
        }
        return R.Failed ( "删除失败" );
    }

    @Override
    public R<DataAssetInfo> updatestatusbash(List<UpdateDataAssetInfoStatusDto> updateDataAssetInfoStatusDtos) {
        if (updateDataAssetInfoStatusDtos == null || updateDataAssetInfoStatusDtos.isEmpty ()) {
            return R.Failed ( "输入数据为空" );
        }
        boolean allUpdateSuccess = true;
        for (UpdateDataAssetInfoStatusDto dto : updateDataAssetInfoStatusDtos) {
            DataAssetInfo one = this.getOne ( new LambdaQueryWrapper<DataAssetInfo> ().eq ( DataAssetInfo::getId, dto.getId () )
                    .eq ( DataAssetInfo::getDeleted, 0 ) );
            if (one == null) {
                allUpdateSuccess = false;
                continue;
            }
            DataAssetInfo dataAssetInfo = new DataAssetInfo ();
            dataAssetInfo.setUpdateTime ( LocalDateTime.now () );
            boolean update = this.update ( new LambdaUpdateWrapper<DataAssetInfo> ().set ( DataAssetInfo::getStatus, dto.getStatus () )
                    .eq ( DataAssetInfo::getId, dto.getId () ) );
            if (!update) {
                allUpdateSuccess = false;
            }
        }
        if (allUpdateSuccess) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        } else {
            return R.Failed ( "部分更新失败，可能是由于某些字典项已被删除或更新条件不匹配" );
        }
    }

    @Override
    public R<DataAssetInfo> searchdetail(SearchDataAssetInfoDetailDto searchDataAssetInfoDetailDto) {
        //首先拿到需要的数据资产数据
        DataAssetInfo one = this.getOne ( new LambdaQueryWrapper<DataAssetInfo> ().eq ( DataAssetInfo::getId, searchDataAssetInfoDetailDto.getId () )
                .eq ( DataAssetInfo::getDeleted, 0 ) );
        if (one == null) {
            return R.Failed ( "未找到对应的数据" );
        }
        //得到该数据资产对应的编号;
        Integer id = one.getId ();
        int classifyid = dataAssetCatalogMapper.search ( id );
        //根据该id寻找对应的数据资产字段信息
        List<DataAssetField> list = dataAssetFieldService.list ( new LambdaQueryWrapper<DataAssetField> ().eq ( DataAssetField::getDataAssetId, id ) );
        if (list == null || list.isEmpty ()) {
            return R.Failed ( "没有找到对应的数据资产字段" );
        }
        SearchDataAssetDetailVo searchDataAssetDetailVo = new SearchDataAssetDetailVo ();
        searchDataAssetDetailVo.setChineseName ( one.getChineseName () );
        searchDataAssetDetailVo.setEnglishName ( one.getEnglishName () );
        searchDataAssetDetailVo.setDescription ( one.getDescription () );
        searchDataAssetDetailVo.setClassifyId ( classifyid );
        searchDataAssetDetailVo.setDataAssetFields ( list );
        return R.Success ( searchDataAssetDetailVo );
    }
}
